package com.zz.inventory.service.impl;

import java.util.*;

import com.zz.inventory.domain.Clients;
import com.zz.inventory.domain.ServiceResult;
import com.zz.inventory.mapper.ClientsMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.formula.functions.T;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.ruoyi.common.core.utils.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.zz.inventory.mapper.LabsMapper;
import com.zz.inventory.domain.Labs;
import com.zz.inventory.service.ILabsService;
import org.springframework.transaction.annotation.Transactional;

/**
 * 机房信息Service业务层处理
 * 
 * @author ruoyi
 * @date 2025-07-01
 */
@Service
@Slf4j
public class LabsServiceImpl implements ILabsService 
{
    @Autowired
    private LabsMapper labsMapper;
    @Autowired
    private ClientsMapper clientsMapper;

    /**
     * 查询机房信息
     * 
     * @param labId 机房信息主键
     * @return 机房信息
     */
    @Override
    public Labs selectLabsByLabId(Long labId)
    {
        return labsMapper.selectLabsByLabId(labId);
    }

    /**
     * 查询机房信息列表
     * 
     * @param labs 机房信息
     * @return 机房信息
     */
    @Override
    public List<Labs> selectLabsList(Labs labs)
    {
        return labsMapper.selectLabsList(labs);
    }

    /**
     * 新增机房信息
     * 
     * @param labs 机房信息
     * @return 结果
     */
    @Override
    public int insertLabs(Labs labs)
    {
        labs.setCreateTime(DateUtils.getNowDate());
        return labsMapper.insertLabs(labs);
    }

    /**
     * 修改机房信息
     * 
     * @param labs 机房信息
     * @return 结果
     */
    @Override
    public int updateLabs(Labs labs)
    {
        return labsMapper.updateLabs(labs);
    }

    /**
     * 批量删除机房信息
     * 
     * @param labIds 需要删除的机房信息主键
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ServiceResult<Integer> deleteLabsByLabIds(Long[] labIds) {
        if (labIds == null || labIds.length == 0) {
            return ServiceResult.fail("请选择需要删除的机房信息");
        }

        // 1. 检查每个机房是否被学校使用
        StringBuilder errorMsg = new StringBuilder();
        for (Long labId : labIds) {
            if (isLabUsedBySchool(labId)) {
                Labs lab = selectLabsByLabId(labId);
                String labName = lab != null ? lab.getLabName() : "ID" + labId;
                errorMsg.append("【").append(labName).append("】已有学校使用，无法删除；");
            }
        }

        // 2. 如果存在被学校使用的机房，直接返回失败
        if (errorMsg.length() > 0) {
            return ServiceResult.fail(errorMsg.toString());
        }

        // 3. 查询所有待删除机房关联的有效考试数量
        List<Long> labIdList = Arrays.asList(labIds);
        List<Map<String, Object>> relatedExams = labsMapper.countRelatedExamsBatch(labIdList);

        // 4. 转换为Map便于快速查找每个机房的关联考试数量
        Map<Long, Integer> examCountMap = new HashMap<>();
        for (Map<String, Object> exam : relatedExams) {
            examCountMap.put(
                    Long.valueOf(exam.get("lab_id").toString()),
                    Integer.valueOf(exam.get("exam_count").toString())
            );
        }

        // 5. 检查是否存在关联考试的机房
        for (Long labId : labIds) {
            int count = examCountMap.getOrDefault(labId, 0);
            if (count > 0) {
                Labs lab = selectLabsByLabId(labId);
                String labName = lab != null ? lab.getLabName() : "ID" + labId;
                errorMsg.append("【").append(labName).append("】关联了").append(count).append("场考试，无法删除；");
            }
        }

        // 6. 如果存在关联考试的机房，返回失败
        if (errorMsg.length() > 0) {
            return ServiceResult.fail(errorMsg.toString());
        }

        // 7. 执行删除
        int count = labsMapper.deleteLabsByLabIds(labIds);
        return ServiceResult.success(count);
    }
    /**
     * 删除机房信息信息
     *
     * @param labId 机房信息主键
     * @return 结果
     */
    @Override
    @Transactional
    public ServiceResult<Integer> deleteLabsByLabId(Long labId) {
        return deleteLabsByLabIds(new Long[]{labId});
    }
    @Override
    public boolean isLabUsedBySchool(Long labId) {
        // 1. 查询 labs 表中该 labId 对应的 school_id
        Labs lab = labsMapper.selectLabsByLabId(labId); // 需实现 selectLabsByLabId 方法
        if (lab == null) {
            return false; // 机房不存在，无需检查
        }

        Long schoolId = lab.getSchoolId();
        // 2. 调用 Mapper 检查关联
        return labsMapper.countSchoolUsingLab(schoolId) > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateLabStatusByClient(Long clientId, String clientStatus) {
        // 1. 获取客户端信息
        Clients client = clientsMapper.selectClientsByClientId(clientId);
        if (client == null || client.getLabId() == null) {
            log.warn("客户端{}不存在或未分配机房", clientId);
            return;
        }

        // 2. 获取该机房下所有客户端
        List<Clients> clientsInLab = clientsMapper.selectClientsByLabId(client.getLabId());
        if (clientsInLab.isEmpty()) {
            log.warn("机房{}下没有客户端", client.getLabId());
            return;
        }

        // 3. 分析机房整体状态
        String labStatus = determineLabStatus(clientsInLab);
        log.info("客户端{}状态变更为{}，机房{}状态更新为{}",
                clientId, clientStatus, client.getLabId(), labStatus);

        // 4. 更新机房状态
        updateLabStatus(client.getLabId(), labStatus);
    }
    @Override
    public String determineLabStatus(List<Clients> clients) {
        boolean hasOnline = false;
        boolean allOffline = true;
        boolean hasNoHeartbeat = false;

        for (Clients client : clients) {
            // 检查在线状态
            if ("online".equals(client.getStatus())) {
                hasOnline = true;
                allOffline = false;
            }
            // 检查心跳时间（只有从未上报过心跳才算维护）
            if (client.getLastHeartbeat() == null) {
                hasNoHeartbeat = true;
            }
            // 如果有客户端明确设为维护状态
            if ("maintenance".equals(client.getStatus())) {
                return "maintenance";
            }
        }

        // 状态优先级: 维护中 > 使用中 > 可用
        if (hasNoHeartbeat) {
            return "maintenance";
        } else if (hasOnline) {
            return "in_use";
        } else {
            return "available"; // 所有客户端离线且有心跳记录
        }
    }

    /**
     * 更新机房状态
     */
    public void updateLabStatus(Long labId, String status) {
        Labs lab = new Labs();
        lab.setLabId(labId);
        lab.setStatus(status);
        labsMapper.updateLabs(lab);
    }
}
